package com.wngbms.async;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class CompletableFutureDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

//        m1();
//        m2();

        ExecutorService service = Executors.newFixedThreadPool(3);
        CompletionService<Integer> cs = new ExecutorCompletionService<>(service);

        cs.submit(() -> {
            log.info("submit1");
            return 35;
        });
        cs.submit(() -> {
            log.info("submit2");
            return 89;
        });
        Future<Integer> submit3 = cs.submit(() -> {
            log.info("submit3");
            sleep(5);
            log.info("submit3 end");
            return 90;
        });

        for (int i = 0; i < 3; i++) {
            if (i == 2) {
                submit3.cancel(true);
            }
            log.info("take:{}", cs.take().get());
        }
    }

    private static void m2() throws InterruptedException, ExecutionException {
        CompletableFuture<Integer> f0 = CompletableFuture
                .supplyAsync(() -> 3 / 0)
                .thenApply(r -> r * r)
                .exceptionally(e -> -1)
                .handle((x, y) -> {
                    log.info("handle x:{} y:{}", x, y);
                    return 999;
                }).whenComplete((x, y) -> {
                    log.info("whenComplete x:{} y:{}", x, y);
                });
        log.info(String.valueOf(f0.get()));
    }

    private static void m1() throws InterruptedException, ExecutionException {
        CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> {
            log.info("洗水壶");
            sleep(1);

            log.info("烧开水");
            sleep(15);
        });

        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
            log.info("洗茶壶");
            sleep(1);
            log.info("洗茶杯");
            sleep(2);
            log.info("拿茶叶");
            sleep(1);
            return "龙井";
        });

        CompletableFuture<String> f3 = f1.thenCombine(f2, (__, y) -> {
            log.info("y is {}", y);
            return "上茶" + y;
        });

        log.info("end : {}", f3.get());
    }

    public static void sleep(long t) {
        try {
            TimeUnit.SECONDS.sleep(t);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
